package com.yang.loginunion.spring.boot.starter;

import com.yang.loginunion.spring.boot.starter.properties.*;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.yang.loginunion.core.LoginClient;
import org.yang.loginunion.core.ali.miniapp.AlipayMiniappClient;
import org.yang.loginunion.core.ali.miniapp.request.AlipayMaRequest;
import org.yang.loginunion.core.ali.miniapp.request.IAlipayMaRequest;
import org.yang.loginunion.core.ali.miniappmobile.AlipayMiniappMobileClient;
import org.yang.loginunion.core.ali.miniappmobile.request.AlipayMaMobileRequest;
import org.yang.loginunion.core.ali.miniappmobile.request.IAlipayMaMobileRequest;
import org.yang.loginunion.core.email.EmailCodeBindClient;
import org.yang.loginunion.core.email.EmailCodeClient;
import org.yang.loginunion.core.mobile.LocalMobileClient;
import org.yang.loginunion.core.mobile.MobileCodeBindClient;
import org.yang.loginunion.core.mobile.MobileCodeClient;
import org.yang.loginunion.core.mobile.request.AliyunOneKeyLoginRequest;
import org.yang.loginunion.core.mobile.request.ILocalMobileRequest;
import org.yang.loginunion.core.password.EmailPasswordClient;
import org.yang.loginunion.core.password.MobilePasswordClient;
import org.yang.loginunion.core.password.UserNamePasswordClient;
import org.yang.loginunion.core.qq.QQClient;
import org.yang.loginunion.core.qq.request.APIRequest;
import org.yang.loginunion.core.qq.request.IQQRequest;
import org.yang.loginunion.core.repository.OauthRepository;
import org.yang.loginunion.core.repository.OauthTempRepository;
import org.yang.loginunion.core.repository.PasswordRepository;
import org.yang.loginunion.core.repository.VerifycodeRepository;
import org.yang.loginunion.core.wx.miniapp.WeixinMiniappClient;
import org.yang.loginunion.core.wx.miniapp.request.BinarywangMaRequest;
import org.yang.loginunion.core.wx.miniapp.request.IMaRequest;
import org.yang.loginunion.core.wx.miniappmobile.WeixinMiniappMobileClient;
import org.yang.loginunion.core.wx.miniappmobile.request.BinarywangMaMobileRequest;
import org.yang.loginunion.core.wx.miniappmobile.request.IMaMobileRequest;
import org.yang.loginunion.core.wx.mp.WeixinAppClient;
import org.yang.loginunion.core.wx.mp.WeixinMpClient;
import org.yang.loginunion.core.wx.mp.request.BinarywangMpRequest;
import org.yang.loginunion.core.wx.mp.request.IMpRequest;

/**
 * @author Billyang
 * @date 2024/8/13 16:17
 */
@Configuration
@ConditionalOnBean(OauthRepository.class)
@EnableConfigurationProperties({ LocalMobileProperties.class, WeixinAppProperties.class, WeixinMiniappProperties.class,
        WeixinMiniappMobileProperties.class, WeixinMpProperties.class, AlipayMiniappProperties.class,
        AlipayMiniappMobileProperties.class, QQProperties.class })
public class LoginUnionAutoConfiguration {

    @Bean(LoginType.USERNAME_PASSWORD)
    @ConditionalOnMissingBean(name = LoginType.USERNAME_PASSWORD)
    @ConditionalOnBean(PasswordRepository.class)
    LoginClient usernamePasswordClient(OauthRepository oauthRepository, PasswordRepository passwordRepository) {
        return new UserNamePasswordClient(oauthRepository, passwordRepository);
    }

    @Bean(LoginType.MOBILE_PASSWORD)
    @ConditionalOnMissingBean(name = LoginType.MOBILE_PASSWORD)
    @ConditionalOnBean(PasswordRepository.class)
    LoginClient mobilePasswordClient(OauthRepository oauthRepository, PasswordRepository passwordRepository) {
        return new MobilePasswordClient(oauthRepository, passwordRepository);
    }

    @Bean(LoginType.EMAIL_PASSWORD)
    @ConditionalOnMissingBean(name = LoginType.EMAIL_PASSWORD)
    @ConditionalOnBean(PasswordRepository.class)
    LoginClient emailPasswordClient(OauthRepository oauthRepository, PasswordRepository passwordRepository) {
        return new EmailPasswordClient(oauthRepository, passwordRepository);
    }

    @Bean(LoginType.LOCAL_MOBILE)
    @ConditionalOnMissingBean(name = LoginType.LOCAL_MOBILE)
    @ConditionalOnProperty(prefix = "login-union.localMobile", name = "accessKeyId")
    LoginClient localMobileClient(OauthRepository oauthRepository, LocalMobileProperties properties) {
        String accessKeyId = properties.getAccessKeyId();
        String accessKeySecret = properties.getAccessKeySecret();
        String endpoint = properties.getEndpoint();
        ILocalMobileRequest localMobileRequest = new AliyunOneKeyLoginRequest(accessKeyId, accessKeySecret, endpoint);
        return new LocalMobileClient(oauthRepository, localMobileRequest);
    }

    @Bean(LoginType.MOBILE_CODE)
    @ConditionalOnMissingBean(name = LoginType.MOBILE_CODE)
    @ConditionalOnBean(VerifycodeRepository.class)
    LoginClient mobileCodeClient(OauthRepository oauthRepository, VerifycodeRepository verifycodeRepository) {
        return new MobileCodeClient(oauthRepository, verifycodeRepository);
    }

    @Bean(LoginType.MOBILE_CODE_BIND)
    @ConditionalOnMissingBean(name = LoginType.MOBILE_CODE_BIND)
    @ConditionalOnBean({ OauthTempRepository.class, VerifycodeRepository.class })
    LoginClient mobileCodeBindClient(OauthRepository oauthRepository, OauthTempRepository oauthTempRepository,
                                     VerifycodeRepository verifycodeRepository) {
        return new MobileCodeBindClient(oauthRepository, oauthTempRepository, verifycodeRepository);
    }

    @Bean(LoginType.EMAIL_CODE)
    @ConditionalOnMissingBean(name = LoginType.EMAIL_CODE)
    @ConditionalOnBean(VerifycodeRepository.class)
    LoginClient emailCodeClient(OauthRepository oauthRepository, VerifycodeRepository verifycodeRepository) {
        return new EmailCodeClient(oauthRepository, verifycodeRepository);
    }

    @Bean(LoginType.EMAIL_CODE_BIND)
    @ConditionalOnMissingBean(name = LoginType.EMAIL_CODE_BIND)
    @ConditionalOnBean({ OauthTempRepository.class, VerifycodeRepository.class })
    LoginClient emailCodeBindClient(OauthRepository oauthRepository, OauthTempRepository oauthTempRepository,
                                    VerifycodeRepository verifycodeRepository) {
        return new EmailCodeBindClient(oauthRepository, oauthTempRepository, verifycodeRepository);
    }

    @Bean(LoginType.WEIXIN_APP)
    @ConditionalOnMissingBean(name = LoginType.WEIXIN_APP)
    @ConditionalOnBean(OauthTempRepository.class)
    @ConditionalOnProperty(prefix = "login-union.weixinApp", name = "appid")  //只有在该属性存在时才加载bean
    LoginClient weixinAppClient(OauthRepository oauthRepository, OauthTempRepository oauthTempRepository,
                                WeixinAppProperties properties) {
        String appid = properties.getAppid();
        String secret = properties.getSecret();

        IMpRequest mpRequest = new BinarywangMpRequest(appid, secret);
        return new WeixinAppClient(oauthRepository, oauthTempRepository, mpRequest);
    }

    @Bean(LoginType.WEIXIN_MINIAPP)
    @ConditionalOnMissingBean(name = LoginType.WEIXIN_MINIAPP)
    @ConditionalOnProperty(prefix = "login-union.weixinMiniapp", name = "appid")
    LoginClient weixinMiniappClient(OauthRepository oauthRepository, WeixinMiniappProperties properties) {
        String appid = properties.getAppid();
        String secret = properties.getSecret();

        IMaRequest maRequest = new BinarywangMaRequest(appid, secret);
        return new WeixinMiniappClient(oauthRepository, maRequest);
    }

    @Bean(LoginType.WEIXIN_MINIAPP_MOBILE)
    @ConditionalOnMissingBean(name = LoginType.WEIXIN_MINIAPP_MOBILE)
    @ConditionalOnProperty(prefix = "login-union.weixinMiniappMobile", name = "appid")
    LoginClient weixinMiniappMobileClient(OauthRepository oauthRepository, WeixinMiniappMobileProperties properties) {
        String appid = properties.getAppid();
        String secret = properties.getSecret();

        IMaMobileRequest maRequest = new BinarywangMaMobileRequest(appid, secret);
        return new WeixinMiniappMobileClient(oauthRepository, maRequest);
    }

    @Bean(LoginType.WEIXIN_MP)
    @ConditionalOnMissingBean(name = LoginType.WEIXIN_MP)
    @ConditionalOnBean(OauthTempRepository.class)
    @ConditionalOnProperty(prefix = "login-union.weixinMp", name = "appid")
    LoginClient weixinMpClient(OauthRepository oauthRepository, OauthTempRepository oauthTempRepository,
                               WeixinMpProperties properties) {
        String appid = properties.getAppid();
        String secret = properties.getSecret();

        IMpRequest mpRequest = new BinarywangMpRequest(appid, secret);
        return new WeixinMpClient(oauthRepository, oauthTempRepository, mpRequest);
    }

    @Bean(LoginType.ALIPAY_MINIAPP)
    @ConditionalOnMissingBean(name = LoginType.ALIPAY_MINIAPP)
    @ConditionalOnProperty(prefix = "login-union.alipayMiniapp", name = "appid")
    LoginClient alipayMiniappClient(OauthRepository oauthRepository, AlipayMiniappProperties properties) {
        String aesKey = properties.getAesKey();
        String appid = properties.getAppid();
        String privateKey = properties.getPrivateKey();
        String publicKey = properties.getPublicKey();

        IAlipayMaRequest alipayMaRequest = new AlipayMaRequest(aesKey, appid, privateKey, publicKey);
        return new AlipayMiniappClient(oauthRepository, alipayMaRequest);
    }

    @Bean(LoginType.ALIPAY_MINIAPP_MOBILE)
    @ConditionalOnMissingBean(name = LoginType.ALIPAY_MINIAPP_MOBILE)
    @ConditionalOnProperty(prefix = "login-union.alipayMiniappMobile", name = "appid")
    LoginClient alipayMiniappMobileClient(OauthRepository oauthRepository, AlipayMiniappMobileProperties properties) {
        String appid = properties.getAppid();
        String privateKey = properties.getPrivateKey();
        String publicKey = properties.getPublicKey();

        IAlipayMaMobileRequest alipayMaMobileRequest = new AlipayMaMobileRequest(appid, privateKey, publicKey);
        return new AlipayMiniappMobileClient(oauthRepository, alipayMaMobileRequest);
    }

    @Bean(LoginType.QQ)
    @ConditionalOnMissingBean(name = LoginType.QQ)
    @ConditionalOnProperty(prefix = "login-union.qq", name = "appid")
    LoginClient qqClient(OauthRepository oauthRepository, OauthTempRepository oauthTempRepository,
                         QQProperties properties) {
        String appid = properties.getAppid();
        String appkey = properties.getAppkey();

        IQQRequest qqRequest = new APIRequest(appid, appkey);
        return new QQClient(oauthRepository, oauthTempRepository, qqRequest);
    }
}
